package com.cman777.springc.web.filter;

import com.cman777.springc.common.helper.RandomUtil;
import com.cman777.springc.web.holder.RequestInfoHolder;
import com.cman777.springc.web.util.IpUtil;
import com.cman777.springc.web.util.ServletRequestUtil;
import org.slf4j.MDC;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @author chenzhicong
 * @time 2019/11/9 16:53
 * @description
 */
public class MdcFilter extends OncePerRequestFilter {
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {

        try {
            /**
             * 引入这个mdc(每个线程打印日志时会将mdc里面的东西打印出来)，
             * 是为了在日志里面，同一个请求能看完这个请求整套的日志输出，
             * 方便用 grep
             */
            MDC.put("requestId", RandomUtil.did());
            RequestInfoHolder.init();
            String body = ServletRequestUtil.getStringFromBody(request);
            RequestInfoHolder.setBody(body);
            RequestInfoHolder.setIp(IpUtil.getIp(request));
            RequestInfoHolder.setUri(request.getRequestURI().replaceAll("/+","/"));
            RequestInfoHolder.setMethod(request.getMethod());
            RequestInfoHolder.setRequest(request);

            //因为获取了一次Body 所以封装一个新的request
            HttpServletRequest newHttpServletRequest = request;
            PutStringToBodyWrapper putStringToBodyWrapper = new PutStringToBodyWrapper(request);
            putStringToBodyWrapper.setBody(body);
            newHttpServletRequest = putStringToBodyWrapper;
            logger.info("接收到请求。uri:"
                    + RequestInfoHolder.getMethod() + " " + RequestInfoHolder.getUri()
                       +",ip:" + RequestInfoHolder.getIp()  );
            filterChain.doFilter(newHttpServletRequest,response);
        } finally {
            logger.info("请求结束");
            MDC.clear();
            RequestInfoHolder.remove();
        }
    }
}
